﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using NetDon.OA.Interface.Configuration;
using log4net;
using NetDon.OA.Interface;
using NetDon.Utilities;

namespace NetDon.OA.Business
{
    using Data.EntityClasses;


    public class LogService : ILogService
    {
        private class LogWorkArgument
        {
            public LoggingEvent LoggingEvent;
            public string ApplicationName;
        }
        #region Implementation of ILogService

        public void Log(LoggingEvent logEvent)
        {

            System.Threading.SynchronizationContext context = AsyncOperationManager.SynchronizationContext;
            try
            {
               
                //在记录日志之前先查询出ApplicationName，避免在BackgroundWorker中异步操作的过程中读取ASP.NET Cache缓存出现错误
                var argument = new LogWorkArgument
                                   {
                                       LoggingEvent = logEvent,
                                       ApplicationName = SystemConfiguration.ApplicationName
                };

                // 通过替换SynchronizationContext的方法避免在WebPage中由于未设置Async = true的情况下所出现的异常
                // 此解决方案参考http://www.cnblogs.com/xiaotie/archive/2008/07/25/1251269.html

                AsyncOperationManager.SynchronizationContext = new System.Threading.SynchronizationContext();
                // 使用异步的方法写入log，从而避免写入数据库的时间等待。
                var worker = new BackgroundWorker();
                worker.DoWork += WriteLog;
                worker.RunWorkerAsync(argument);
            }
            catch (Exception e)
            {
                ILog logger = LogManager.GetLogger(typeof(LogService));
                logger.Error(e.Message, e);
            }
            finally
            {
                AsyncOperationManager.SynchronizationContext = context;
            }
        }

        private void WriteLog(object sender, DoWorkEventArgs e)
        {
            var argument = (LogWorkArgument)e.Argument;
            new LogEntity
            {
                Source = argument.LoggingEvent.Source,
                UserName = argument.LoggingEvent.UserName,
                ApplicationName = argument.ApplicationName,
                Message = argument.LoggingEvent.Message,
                Category = argument.LoggingEvent.Category,
                Level = (int)argument.LoggingEvent.Level
            }.Save();
        }

        #endregion
    }
}
